/**
 * 请求工具模块
 * 基于axios封装的HTTP请求工具
 * 提供统一的请求拦截、响应拦截和错误处理
 */

import axios from 'axios'
import { ElMessage } from 'element-plus'
import router from '@/router'

/**
 * 创建axios实例
 * 配置基础URL、超时时间和请求头
 */
const service = axios.create({
  baseURL: 'http://localhost:9999', // 设置基础URL
  timeout: 30000, // 请求超时时间（30秒）
  headers: {
    'Content-Type': 'application/json',  // 默认请求头
    'Accept': 'application/json'
  },
  withCredentials: true // 允许跨域携带cookie
})

// 公开路径配置
const publicPaths = [
  '/login',
  '/register',
  '/public',
  '/captchaService/captcha',
  '/userService/userController/sendRegisterMessageCode',
  '/userService/userController/checkRegisterMessageCode',
  '/userService/userController/sendLoginMessageCode',
  '/userService/userController/checkLoginMessageCode',
  '/userService/userController/verifyToken',
  '/userService/userController/sendResetMessageCode',
  '/userService/userController/checkResetMessageCode',
  '/userService/userController/resetPassword',
  '/userService/userController/sendResetPhoneCode',
  '/userService/userController/checkResetPhoneCode'
]

/**
 * 检查是否是公开路径
 * @param {string} url - 请求URL
 * @returns {boolean} - 是否是公开路径
 */
const isPublicPath = (url) => {
  // 移除baseURL部分，只比较路径
  const path = url.replace(/^https?:\/\/[^/]+/, '');
  console.debug('检查路径:', path);
  const result = publicPaths.some(publicPath => path.includes(publicPath));
  console.debug('是否是公开路径:', result);
  return result;
}

/**
 * Token管理模块
 */
const TokenManager = {
  // 存储Token
  setToken(token, remember = false) {
    if (!token) return;
    
    // 确保token格式正确
    const normalizedToken = token.startsWith('Bearer ') ? token : `Bearer ${token}`;
    
    if (remember) {
      localStorage.setItem('token', normalizedToken);
      console.debug('Token已存储到localStorage');
    }
    sessionStorage.setItem('token', normalizedToken);
    console.debug('Token已存储到sessionStorage');
  },
  
  // 获取Token
  getToken() {
    return sessionStorage.getItem('token') || localStorage.getItem('token');
  },
  
  // 清除Token
  clearToken() {
    sessionStorage.removeItem('token');
    localStorage.removeItem('token');
    console.debug('Token已清除');
  },
  
  // 规范化Token
  normalizeToken(token) {
    if (!token) return null;
    return token.startsWith('Bearer ') ? token : `Bearer ${token}`;
  }
};

/**
 * 获取规范化的Token
 * @returns {string|null} - 返回规范化的Token或null
 */
const getNormalizedToken = () => {
  try {
    const token = TokenManager.getToken();
    if (!token) {
      console.debug('未找到Token');
      return null;
    }
    return TokenManager.normalizeToken(token);
  } catch (error) {
    console.error('获取Token时发生错误:', error);
    return null;
  }
};

/**
 * 请求拦截器
 * 在发送请求前统一处理token和请求头
 */
service.interceptors.request.use(
  config => {
    const requestUrl = config.url;
    console.debug(`准备发送请求: ${config.method?.toUpperCase()} ${requestUrl}`);
    
    // 检查是否是公开路径
    const isPublic = isPublicPath(requestUrl);
    console.debug('是否为公开路径:', isPublic, '请求URL:', requestUrl);
    
    // 获取规范化的Token
    const token = getNormalizedToken();
    
    // 设置CORS相关头
    config.headers['Access-Control-Allow-Origin'] = '*';
    config.headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,DELETE,OPTIONS';
    config.headers['Access-Control-Allow-Headers'] = 'Content-Type,Authorization';
    
    // 如果是公开路径，直接发送请求
    if (isPublic) {
      console.debug('公开路径，无需Token验证');
      return config;
    }
    
    // 非公开路径，检查Token
    if (!token) {
      console.warn('访问需要认证的路径，但未找到有效Token');
      // 如果当前不在登录页，才显示提示并跳转
      if (router.currentRoute.value.path !== '/login') {
        ElMessage.warning('请先登录');
        router.push({
          path: '/login',
          query: { redirect: router.currentRoute.value.fullPath }
        });
      }
      return Promise.reject(new Error('未登录'));
    }
    
    // 设置Authorization头
    config.headers['Authorization'] = token;
    console.debug('Token已添加到请求头');
    
    return config;
  },
  error => {
    console.error('请求拦截器错误:', error);
    // 检查是否是登录相关的接口
    const isLoginRelated = error.config?.url?.includes('/userService/userController/checkLoginMessageCode') ||
                         error.config?.url?.includes('/userService/userController/sendLoginMessageCode');
    
    // 对于登录相关接口，不显示错误提示
    if (!isLoginRelated) {
      ElMessage.error('请求发送失败');
    }
    return Promise.reject(error);
  }
);

/**
 * 处理大数字的函数
 * 将特定字段的大数字转换为字符串，避免精度丢失
 * @param {any} data - 需要处理的数据
 * @returns {any} 处理后的数据
 */
const handleBigNumber = (data) => {
  // 处理数组类型
  if (Array.isArray(data)) {
    return data.map(item => handleBigNumber(item));
  } 
  // 处理对象类型
  else if (typeof data === 'object' && data !== null) {
    const result = {};
    for (const key in data) {
      // 对特定字段（courseId和conversationId）进行特殊处理
      if ((key === 'courseId' || key === 'conversationId') && typeof data[key] === 'number') {
        result[key] = data[key].toString();
      } else {
        result[key] = handleBigNumber(data[key]);
      }
    }
    return result;
  }
  // 其他类型直接返回
  return data;
};

/**
 * 响应拦截器
 * 统一处理响应数据和错误
 */
service.interceptors.response.use(
  response => {
    const handledData = handleBigNumber(response.data)
    
    // 记录调试信息
    console.log(`响应URL: ${response.config.url}, 响应数据:`, handledData)
    
    // 如果是verifyToken接口，不显示任何错误消息
    if (response.config.url.includes('/userService/userController/verifyToken')) {
      return handledData
    }

    // 如果是订单查询接口，直接返回数据
    if (response.config.url.includes('/ordersService/ordersController/selectAllOrders')) {
      return handledData
    }

    // 如果code为401，可能是token失效
    if (handledData.code === 401) {
      console.log('响应状态码为401，token可能已失效')
      // 清除token
      TokenManager.clearToken()
      
      // 如果不是登录页面，则重定向到登录页
      if (router.currentRoute.value.path !== '/login') {
        ElMessage({
          message: '登录已过期，请重新登录',
          type: 'warning',
          duration: 3000
        })
        router.push({
          path: '/login',
          query: { redirect: router.currentRoute.value.fullPath }
        })
      }
      return Promise.reject(new Error('登录已过期，请重新登录'))
    }

    // 处理其他接口的响应
    if (handledData.code !== undefined && handledData.code !== 200) {
      return Promise.reject(new Error(handledData.message || '未知错误'))
    }
    
    return handledData
  },
  error => {
    console.error('响应错误:', error)
    
    if (error.response) {
      const status = error.response.status
      const url = error.response.config.url
      console.error(`HTTP状态码: ${status}`)
      
      // 检查是否是登录相关的接口
      const isLoginRelated = url.includes('/userService/userController/checkLoginMessageCode') ||
                           url.includes('/userService/userController/sendLoginMessageCode')
      
      // 对于401状态码，静默处理（不显示消息）
      if (status === 401) {
        console.error('Token无效或已过期')
        TokenManager.clearToken()
        if (router.currentRoute.value.path !== '/login') {
          router.push('/login')
        }
        return Promise.reject(error)
      }
      
      // 对于登录相关接口，不显示错误提示
      if (isLoginRelated) {
        return Promise.reject(error)
      }
      
      // 其他错误统一显示简单的错误提示
      ElMessage.error('请求失败，请稍后重试')
    } else if (error.request) {
      console.error('未收到响应')
      // 检查是否是登录相关的接口
      const isLoginRelated = error.config?.url?.includes('/userService/userController/checkLoginMessageCode') ||
                           error.config?.url?.includes('/userService/userController/sendLoginMessageCode');
      if (!isLoginRelated) {
        ElMessage.error('网络连接失败')
      }
    } else {
      console.error('请求配置错误')
      // 检查是否是登录相关的接口
      const isLoginRelated = error.config?.url?.includes('/userService/userController/checkLoginMessageCode') ||
                           error.config?.url?.includes('/userService/userController/sendLoginMessageCode');
      if (!isLoginRelated) {
        ElMessage.error('请求失败')
      }
    }
    
    return Promise.reject(error)
  }
)

export { TokenManager };
export default service